from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from datetime import datetime
from werkzeug.security import generate_password_hash, check_password_hash
from sqlalchemy import Date

db = SQLAlchemy()
migrate = Migrate()


class User(db.Model):
    __tablename__ = 'users'  # 数据库表名
    id = db.Column(db.Integer, primary_key=True)  # 主键
    username = db.Column(db.String(64), unique=True, nullable=False, comment='用户名')  # 用户名，唯一且不能为空
    email = db.Column(db.String(120), unique=True, nullable=False, comment='邮箱')  # 邮箱，唯一且不能为空
    password_hash = db.Column(db.String(128), nullable=False, comment='密码哈希值')  # 密码哈希值，不能为空
    created_at = db.Column(db.DateTime, default=datetime.utcnow, comment='创建时间')  # 创建时间，默认为当前时间
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow,
                           comment='更新时间')  # 更新时间，默认为当前时间，更新时自动更新为当前时间
    # 关联用户配置模型
    user_config = db.relationship('UserConfig', backref='user', uselist=False,
                                  cascade='all, delete-orphan')  # 与用户配置模型建立一对一关系
    study_plans = db.relationship("StudyPlan", back_populates="user")
    # 建立与 Note 的关系
    notes = db.relationship('Note', back_populates='user')
    translations = db.relationship('Translation', back_populates='user')
    chat_sessions = db.relationship('ChatSession', back_populates='user')

    def set_password(self, password):
        """设置密码，生成密码哈希值"""
        self.password_hash = generate_password_hash(password)

    def check_password(self, password):
        """验证密码，检查密码是否正确"""
        return check_password_hash(self.password_hash, password)


class UserConfig(db.Model):
    __tablename__ = 'user_configs'  # 数据库表名
    id = db.Column(db.Integer, primary_key=True)  # 主键
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), unique=True, nullable=False,
                        comment='用户ID')  # 外键，关联到用户模型的 id 字段，唯一且不能为空
    gender = db.Column(db.String(10), nullable=False, comment='性别')  # 性别，不能为空
    bio = db.Column(db.Text, nullable=True, comment='个人介绍')  # 个人介绍，可为空
    location = db.Column(db.String(100), nullable=True, comment='所在地区')  # 所在地区，可为空
    birth_date = db.Column(Date, nullable=True, comment='出生日期')  # 出生日期，可为空
    avatar = db.Column(db.String(255), nullable=True, comment='头像路径或头像地址')

    def to_json(self):
        return {
            'id': self.id,
            'user_id': self.user_id,
            'gender': self.gender,
            'bio': self.bio,
            'location': self.location,
            'birth_date': self.birth_date.isoformat() if self.birth_date else None,
            'avatar': self.avatar
        }


class StudyPlan(db.Model):
    __tablename__ = 'study_plans'  # 数据库表名
    id = db.Column(db.Integer, primary_key=True)  # 主键
    subject = db.Column(db.String(100), nullable=False, comment='学习科目')  # 学习科目，不能为空
    goal = db.Column(db.String(200), nullable=False, comment='学习目标')  # 学习目标，不能为空
    duration = db.Column(db.Integer, nullable=False, comment='学习时长（天数）')  # 学习时长，以天为单位，不能为空
    plan = db.Column(db.Text, nullable=True, comment='学习计划的详细内容')  # 学习计划的详细内容，可为空

    # 外键，关联到 User 模型的 id 字段
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    user = db.relationship('User', back_populates='study_plans')

    def __repr__(self):
        return f"<StudyPlan(id={self.id}, subject='{self.subject}', goal='{self.goal}', duration={self.duration}, plan='{self.plan}')>"


from datetime import datetime


class ChatSession(db.Model):
    __tablename__ = 'chat_sessions'
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    chat_title = db.Column(db.String(255), nullable=False, default="默认标题")
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    # 关系：一个聊天会话对应多个消息
    messages = db.relationship('Message', back_populates='chat_session')
    # 关系：一个聊天会话属于一个用户
    user = db.relationship('User', back_populates='chat_sessions')

    def __repr__(self):
        return f"<ChatSession(id={self.id}, user_id={self.user_id}, created_at='{self.created_at}')>"

    def to_json(self):
        return {
            'id': self.id,
            'user_id': self.user_id,
            'chat_title': self.chat_title,
            'created_at': self.created_at.isoformat(),
            'messages': [message.to_json() for message in self.messages]
        }


class Message(db.Model):
    __tablename__ = 'messages'
    id = db.Column(db.Integer, primary_key=True)
    chat_session_id = db.Column(db.Integer, db.ForeignKey('chat_sessions.id'), nullable=False)
    question = db.Column(db.Text, nullable=False)
    answer = db.Column(db.Text, nullable=True)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    answered_at = db.Column(db.DateTime, nullable=True)
    # 关系：一条消息属于一个聊天会话
    chat_session = db.relationship('ChatSession', back_populates='messages')

    def __repr__(self):
        return f"<Message(id={self.id}, chat_session_id={self.chat_session_id}, question='{self.question}', answer='{self.answer}', created_at='{self.created_at}', answered_at='{self.answered_at}')>"

    def to_json(self):
        return {
            'id': self.id,
            'chat_session_id': self.chat_session_id,
            'question': self.question,
            'answer': self.answer,
            'created_at': self.created_at.isoformat(),
            'answered_at': self.answered_at.isoformat() if self.answered_at else None
        }


class Note(db.Model):
    __tablename__ = 'notes'  # 数据库表名
    id = db.Column(db.Integer, primary_key=True)  # 主键
    title = db.Column(db.String(200), nullable=False, comment='标题')  # 标题，不能为空
    content = db.Column(db.Text, nullable=False, comment='具体内容')  # 具体内容，不能为空
    summary = db.Column(db.String(500), nullable=True, comment='摘要')  # 摘要，可为空
    created_at = db.Column(db.DateTime, default=datetime.utcnow, comment='创建时间')  # 创建时间，默认为当前时间
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow,
                           comment='更新时间')  # 更新时间，默认为当前时间，更新时自动更新

    # 外键，关联到 User 模型的 id 字段
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    user = db.relationship('User', back_populates='notes')

    def __repr__(self):
        return f"<Note(id={self.id}, title='{self.title}', summary='{self.summary}', created_at='{self.created_at}')>"

    def to_json(self):
        return {
            'id': self.id,
            'title': self.title,
            'content': self.content,
            'summary': self.summary,
            'created_at': self.created_at.isoformat(),
            'updated_at': self.updated_at.isoformat()
        }


class Translation(db.Model):
    __tablename__ = 'translations'  # 数据库表名
    id = db.Column(db.Integer, primary_key=True)  # 主键
    source_language = db.Column(db.String(10), nullable=False, comment='当前语言')  # 当前语言，不能为空
    target_language = db.Column(db.String(10), nullable=False, comment='目标语言')  # 目标语言，不能为空
    is_file = db.Column(db.Boolean, default=False, comment='是否为文件翻译')  # 是否为文件翻译，默认为 False
    original_text = db.Column(db.Text, nullable=False, comment='原文')  # 原文，不能为空
    translated_text = db.Column(db.Text, nullable=True, comment='翻译结果')  # 翻译结果，可为空
    created_at = db.Column(db.DateTime, default=datetime.utcnow, comment='创建时间')  # 创建时间，默认为当前时间
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow,
                           comment='更新时间')  # 更新时间，默认为当前时间，更新时自动更新

    # 外键，关联到 User 模型的 id 字段
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    user = db.relationship('User', back_populates='translations')

    def __repr__(self):
        return f"<Translation(id={self.id}, source_language='{self.source_language}', target_language='{self.target_language}', is_file={self.is_file}, original_text='{self.original_text[:30]}...', translated_text='{self.translated_text[:30]}...')>"

    def to_json(self):
        return {
            'id': self.id,
            'source_language': self.source_language,
            'target_language': self.target_language,
            'is_file': self.is_file,
            'original_text': self.original_text,
            'translated_text': self.translated_text,
            'created_at': self.created_at.isoformat(),
            'updated_at': self.updated_at.isoformat()
        }


def init_db(app: Flask):
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    db.init_app(app)
    migrate.init_app(app, db)
    with app.app_context():
        db.create_all()
